package com.xk.sport.backend.service;

import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.xk.sport.backend.common.entity.TeacherQuery;
import com.xk.sport.backend.common.util.DesUtil;
import com.xk.sport.backend.dao.model.Area;
import com.xk.sport.backend.dao.model.Lesson;
import com.xk.sport.backend.dao.model.Teacher;
import com.xk.sport.backend.dao.model.TeacherLesson;
import com.xk.sport.backend.dao.repository.AreaDao;
import com.xk.sport.backend.dao.repository.LessonDao;
import com.xk.sport.backend.dao.repository.TeacherDao;
import com.xk.sport.backend.dao.repository.TeacherLessonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;

@Service
public class TeacherService {

    @Autowired
    private TeacherDao teacherDao;
    @Autowired
    private TeacherLessonDao teacherLessonDao;
    @Autowired
    private LessonDao lessonDao;
    @Autowired
    private AreaDao areaDao;

    /**
     * 查询
     */
    public Page<Teacher> findAllByQueryAndPage(final TeacherQuery query) {
        Pageable pageable = new PageRequest(query.getPageNum(), query.getSize(), 0 == query.getSortAsc() ? Sort.Direction.DESC : Sort.Direction.ASC, query.getSortKey());
        Page<Teacher> page = teacherDao.findAll(new Specification<Teacher>() {
            @Override
            public Predicate toPredicate(Root<Teacher> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> list = new ArrayList<Predicate>();
                if (!Strings.isNullOrEmpty(query.getName())) {
                    list.add(criteriaBuilder.like(root.get("name").as(String.class), "%" + query.getName() + "%"));
                }
                if (!Strings.isNullOrEmpty(query.getCode())) {
                    list.add(criteriaBuilder.equal(root.get("code").as(String.class), query.getCode()));
                }
                if (!Strings.isNullOrEmpty(query.getContact())) {
                    list.add(criteriaBuilder.like(root.get("contact").as(String.class), "%" + query.getContact() + "%"));
                }
                return criteriaBuilder.and(list.toArray(new Predicate[0]));
            }
        }, pageable);
        fillTeacherList(page.getContent());
        return page;
    }

    /**
     * 填充
     */
    private void fillTeacherList(List<Teacher> teachers) {
        if (teachers == null || teachers.size() <= 0) {
            return;
        }
        fillTeacher(teachers.toArray(new Teacher[0]));
    }

    // 填充
    private void fillTeacher(Teacher... teachers) {
        if (teachers == null || teachers.length <= 0) {
            return;
        }
        List<Long> teacherIds = new ArrayList<>();
        List<Long> areaIds = new ArrayList<>();
        for (Teacher teacher : teachers) {
            if (teacher == null) {
                continue;
            }
            teacherIds.add(teacher.getId());
            areaIds.add(teacher.getAreaId());
        }
        List<TeacherLesson> tls = teacherLessonDao.findTeacherLessonsByTeacherIds(teacherIds);
        Map<Long, List<TeacherLesson>> tlMap = new HashMap<>();
        if (tls != null && tls.size() > 0) {
            List<Long> lessonIds = new ArrayList<>();
            for (TeacherLesson lesson : tls) {
                long lessonId = lesson.getLessonId();
                long teacherId = lesson.getTeacherId();
                lessonIds.add(lessonId);
                List<TeacherLesson> list = tlMap.get(teacherId);
                if (list == null) {
                    list = new ArrayList<>();
                    list.add(lesson);
                    tlMap.put(teacherId, list);
                } else {
                    list.add(lesson);
                }
            }
            List<Lesson> lessons = lessonDao.findLessonsByIds(lessonIds);
            if (lessons != null && lessons.size() > 0) {
                Map<Long, Lesson> lessonMap = new HashMap<>();
                for (Lesson lesson : lessons) {
                    lessonMap.put(lesson.getId(), lesson);
                }
                for (TeacherLesson tl : tls) {
                    long lessonId = tl.getLessonId();
                    Lesson lesson = lessonMap.get(lessonId);
                    tl.setLesson(lesson);
                }
            }
        }
        List<Area> areas = areaDao.findAreasByIds(areaIds);
        Map<Long, Area> areaMap = new HashMap<>();
        if (areas != null) {
            for (Area area : areas) {
                areaMap.put(area.getId(), area);
            }
        }
        for (Teacher teacher : teachers) {
            if (teacher == null) {
                continue;
            }
            List<TeacherLesson> subtls = tlMap.get(teacher.getId());
            teacher.setLessons(subtls);
            if (subtls != null) {
                List<String> lessonNames = new ArrayList<>();
                for (TeacherLesson tl : subtls) {
                    if (tl != null && tl.getLesson() != null) {
                        lessonNames.add(tl.getLesson().getName());
                    }
                }
                teacher.setLessonNames(Joiner.on(",").join(lessonNames));
            }
            teacher.setArea(areaMap.get(teacher.getAreaId()));
        }
    }

    /**
     * 查询
     */
    public Teacher findOne(long id) {
        Teacher teacher = teacherDao.findOne(id);
        fillTeacher(teacher);
        return teacher;
    }

    /**
     * 按照code查询教师
     */
    public Teacher findOneByCode(String code) {
        return teacherDao.findByCode(code);
    }

    /**
     * 查询指定教师可以教的课程列表
     */
    public Set<Long> findLessonIds(long teacherId) {
        List<TeacherLesson> tls = teacherLessonDao.findTeacherLessonsByTeacherIds(Lists.newArrayList(teacherId));
        Set<Long> set = new HashSet<>();
        if (tls != null) {
            for (TeacherLesson tl : tls) {
                set.add(tl.getLessonId());
            }
        }
        return set;
    }

    /**
     * 添加
     */
    public Teacher add(Teacher teacher) {
        if (teacher == null || teacher.getId() > 0) {
            return null;
        }
        if (Strings.isNullOrEmpty(teacher.getCode())) {
            teacher.setCode(genRandomCode());
        }
        teacher.setCreateTime(System.currentTimeMillis());
        Teacher newTeacher = teacherDao.save(teacher);
        if (newTeacher != null) {
            saveTeacherLessonsByTeacherInfo(teacher, newTeacher);
            fillTeacher(newTeacher);
        }
        return newTeacher;
    }

    private String genRandomCode() {
        long now = System.currentTimeMillis();
        Random random = new Random(1000);
        String source = now + "random" + random.nextInt();
        try {
            String code = DesUtil.encrypt(source, DesUtil.key);
            code = code.replaceAll("\\W", "");
            return code;
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 添加教师-课程关系
     */
    private void saveTeacherLessonsByTeacherInfo(Teacher paramTeacher, Teacher resultTeacher) {
        if (!Strings.isNullOrEmpty(paramTeacher.getLessonNames())) {
            for (String lessonName : paramTeacher.getLessonNames().split(",")) {
                Long[] lessonIds = lessonDao.findIdsByName(lessonName);
                if (lessonIds == null || lessonIds.length <= 0) {
                    continue;
                }
                TeacherLesson tl = new TeacherLesson();
                tl.setTeacherId(resultTeacher.getId());
                tl.setLessonId(lessonIds[0]);
                teacherLessonDao.save(tl);
            }
        }
    }

    /**
     * 修改
     */
    public Teacher update(Teacher teacher) {
        if (teacher == null || teacher.getId() <= 0) {
            return null;
        }
        Teacher newTeacher = teacherDao.save(teacher);
        if (newTeacher != null) {
            teacherLessonDao.deleteTeacherLessonsByTeacherId(teacher.getId());
            saveTeacherLessonsByTeacherInfo(teacher, newTeacher);
            fillTeacher(newTeacher);
        }
        return newTeacher;
    }

    /**
     * 删除
     */
    public boolean delete(long id) {
        teacherDao.delete(id);
        teacherLessonDao.deleteTeacherLessonsByTeacherId(id);
        return true;
    }
}
